﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net.Mail;
using System.Text;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.VersionControl.Client;
using OfficeOpenXml;

namespace Core
{
    public class ReviewNotificator
    {
        private VersionControlServer versionControlServer;
        private ExcelWorksheet worksheet;
        private List<int> processedChangesets = new List<int>();
        private string lastPrimaryReviewer;
        private string lastSecondaryReviewer;
        private int currentRow = 2;

        private const int Reviewer1Column = 6;
        private const int Reviewer2Column = 7;

        public ReviewNotificator(TfsTeamProjectCollection tfspc, ExcelPackage excelPackage)
        {
            versionControlServer = tfspc.GetService<VersionControlServer>();
            worksheet = excelPackage.Workbook.Worksheets[ReportSettings.ReviewLogWorksheet];
            while (worksheet.GetValue(currentRow, 1) != null)
            {
                int changesetId;
                if (int.TryParse(worksheet.GetValue(currentRow, 1).ToString(), out changesetId))
                {
                    processedChangesets.Add(changesetId);
                    if(worksheet.Cells[currentRow, Reviewer1Column].Value != null)
                    {
                        lastPrimaryReviewer = worksheet.Cells[currentRow, Reviewer1Column].Value.ToString();
                    }
                    if (worksheet.Cells[currentRow, Reviewer2Column].Value != null)
                    {
                        lastSecondaryReviewer = worksheet.Cells[currentRow, Reviewer2Column].Value.ToString();
                    }
                }
                currentRow++;
            }
        }

        public void ProcessChangeset(int changesetId)
        {
            if (processedChangesets.Contains(changesetId))
                return;

            var changeset = versionControlServer.GetChangeset(changesetId);

            worksheet.Cells[currentRow, 1].Value = changeset.ChangesetId;
            var commiter = Configuration.Team.GetFirstPersonByLogin(changeset.Committer);
            var commiterName = commiter != null ? commiter.Name : changeset.Committer;
            worksheet.Cells[currentRow, 2].Value = commiterName;
            worksheet.Cells[currentRow, 3].Value = changeset.CreationDate;
            worksheet.Cells[currentRow, 4].Value = changeset.Comment;
            worksheet.Cells[currentRow, 5].Value = string.Join(";", changeset.WorkItems.Select(w => w.Id));

            SendNotification(changeset, commiterName);

            currentRow++;
            processedChangesets.Add(changesetId);
        }

        private void SendNotification(Changeset changeset, string commiterName)
        {
            Person primaryReviewer = Configuration.Team.GetNextPersonByRole("developer", lastPrimaryReviewer);
            if (primaryReviewer.Login == changeset.Committer.ToLower())
            {
                primaryReviewer = Configuration.Team.GetNextPersonByRole("developer", primaryReviewer.Name);
            }
            //Person secondaryReviewer = Configuration.Team.GetNextPersonByRole("coach", lastSecondaryReviewer);
            Person commiter = Configuration.Team.GetFirstPersonByLogin(changeset.Committer);

            worksheet.Cells[currentRow, Reviewer1Column].Value = primaryReviewer.Name;
            //worksheet.Cells[currentRow, Reviewer2Column].Value = secondaryReviewer.Name;

            SmtpClient s = new SmtpClient(Configuration.Exchange);
            s.UseDefaultCredentials = true;
            s.DeliveryMethod = SmtpDeliveryMethod.Network;
            MailMessage m = new MailMessage();
            m.From = new MailAddress(Configuration.Team.TeamLead.Email);
            m.To.Add(primaryReviewer.Email);
            //m.To.Add(secondaryReviewer.Email);
            m.CC.Add(Configuration.Team.TeamLead.Email);
            if (commiter != null)
            {
                m.CC.Add(commiter.Email);
            }

            m.Subject = string.Format("#Code Review# {0}", changeset.ChangesetId);

            StringBuilder body = new StringBuilder();
            body.AppendLine("Hello.");
            body.AppendLine();
            body.AppendFormat("Need to review changeset {0} from {1} commited on {2} {3}.",
                              changeset.ChangesetId,
                              commiterName,
                              changeset.CreationDate.ToShortDateString(),
                              changeset.CreationDate.ToShortTimeString());
            body.AppendLine();
            body.AppendLine();
            body.AppendFormat("Changeset comment: {0}", changeset.Comment);
            body.AppendLine();
            body.AppendLine();

            body.AppendLine("Files was changed:");
            foreach (var change in changeset.Changes)
            {
                body.AppendFormat("{0,-14} {1}",
                                  change.ChangeType.ToString("G"),
                                  change.Item.ServerItem);
                body.AppendLine();
            }

            body.AppendLine();
            body.AppendLine("After review, please reply by email.");
            body.AppendLine();
            body.AppendLine("Best regards,");
            body.AppendLine("Review Notificator Robot.");

            m.Body = body.ToString();
            m.IsBodyHtml = false;
            if(Configuration.SendEmails)
                s.Send(m);

            worksheet.Cells[currentRow, Reviewer2Column+1].Value = DateTime.Now;

            lastPrimaryReviewer = primaryReviewer.Name;
            //lastSecondaryReviewer = secondaryReviewer.Name;

            Trace.WriteLine(
                string.Format("Changeset {0} by {1,-20} processed. Review notification was sent to {2,-20}",
                              changeset.ChangesetId, commiterName, primaryReviewer.Name));
        }
    }
}
